package cn.itrip.auth.controller;

import cn.itrip.auth.config.WXLongConfig;
import cn.itrip.auth.service.TokenService;
import cn.itrip.auth.service.UserLogService;

import cn.itrip.dto.Dto;
import cn.itrip.pojo.ItripUser;
import cn.itrip.utlis.DtoUtils;

import cn.itrip.utlis.RandomUtils;
import cn.itrip.utlis.UrlUtils;
import cn.itrip.vo.ItripTokenVO;
import cn.itrip.vo.ItripWechatTokenVO;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * 第三方登录，微信登录
 */
@Controller
@RequestMapping(value = "/api")
public class WXLogController {

    @Resource
    private UserLogService userLogService;
    @Resource
    private TokenService tokenService;

    /**
     * 转到微信网页进行微信登录
     * @param response
     */
    @ApiOperation(value = "发送微信登录请求！")
    @RequestMapping(value = "/wechat/login",method = RequestMethod.POST)
    public void wechatLogin(HttpServletResponse response){

        //设置state 验证码设定
        int state = RandomUtils.getInteger();

        String qrconnect="https://open.weixin.qq.com/connect/qrconnect?appid="+WXLongConfig.APPID+"&redirect_uri="+WXLongConfig.REDIRECT_URI+"&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect";
        try {
            response.sendRedirect(qrconnect);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 微信回调地址,获取用户授权后，请求微信授权token及用户唯一标识符id 进行查询储存并返回前端数据
     * @param code
     * @param state
     * @param request
     * @param response
     * @throws IOException
     */
    @ApiOperation(value = "微信回调！")
    @RequestMapping(value = "/wechat/callback")
    public void wechatCallback(@RequestParam String code, @RequestParam String state, HttpServletRequest request, HttpServletResponse response) throws IOException{

        //获取登录token 使用微信回调传回来的票据进行下一步操作  获取用户的信息
        String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ WXLongConfig.APPID+"&secret="+WXLongConfig.SECRET+"&code="+ code +"&grant_type=authorization_code";
        response.setContentType("text/html;charset=utf-8");
        //通过url工具获取返回数据
        String json= UrlUtils.loadURL(accessTokenUrl);
        //将返回的JSON字符串转换为Map
        Map<String,Object> wechatToken= JSON.parseObject(json, Map.class);

        try {
            //验证本地库是否存在该用户
            ItripUser user=userLogService.userLogin(wechatToken.get("openid").toString());
            if(user==null){//如果不存在则添加用户
                user=new ItripUser();
                user.setUsercode(wechatToken.get("openid").toString());//微信用户openid作为本地库用户名
                user.setUsertype(1);
				//user.setFlatID(wechatToken.getOpenid());
                user.setUsername(wechatToken.get("openid").toString());
                user.setCreationdate(new Date());
                user.setActivated(1);

                userLogService.saveUser(user);
            }
            //登录后生成的token  返回
            String token = tokenService.createToken(request.getHeader("user-agent"), user);
            tokenService.save(token, user);

            //第一种将返回数据写进请求头

            /*
			response.setHeader("token", token);
			response.setHeader("access_token", wechatToken.get("access_token").toString());
			response.setHeader("expires_in", wechatToken.get("expires_in").toString());
			response.setHeader("refresh_token", wechatToken.get("refresh_token").toString());
			response.setHeader("openid", wechatToken.get("openid").toString());
			*/

            //第二种，将数据写在请求地址上

            /**
             * 将返回token信息 2个 及用户唯一标识openid 返回给前端
             */
            //返回前端处理
            StringBuilder loginPage=new StringBuilder();
            loginPage.append("http://itrip.project.bdqn.cn/#/login");
            //登录生成的token
            loginPage.append("?user_type=1&token="+token);
            //微信请求token
            loginPage.append("&access_token="+wechatToken.get("access_token").toString());
            //微信token有效时间
            loginPage.append("&expires_in="+wechatToken.get("expires_in").toString());
             //刷新请求token 所需token 有效期30天
            loginPage.append("&refresh_token="+wechatToken.get("refresh_token").toString());
            //用户唯一标识
            loginPage.append("&openid="+wechatToken.get("openid").toString());
            response.sendRedirect(loginPage.toString());

        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    //将微信token 及 openid 传递到前端页面之后，再根据 该数据访问如下 接口 获取数据

    /**
     * 获取微信用户信息
     * @param accessToken 微信会话凭据
     * @param openid 微信用户唯一标识
     * @return
     */
    @ApiOperation(value = "获取微信用户信息", httpMethod = "GET",
            protocols = "HTTP", produces = "application/json",
            response = Dto.class,
            notes = "微信登录后，提供客户端获取用户信息操作")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(paramType="query",required=true,name="accessToken",value="微信会话凭据"),
            @ApiImplicitParam(paramType="query",required=true,name="openid",value="微信用户唯一标识")
    })
    @ResponseBody
    @RequestMapping(value = "/wechat/user/info", method = RequestMethod.GET,produces= "application/json")
    public Dto wechatUserInfo(
            @RequestParam String accessToken,
            @RequestParam String openid){
        try {
            //加载用户信息
            String userInfoJson=UrlUtils.loadURL("https://api.weixin.qq.com/sns/userinfo?access_token="
                    +accessToken
                    +"&openid="+ openid
            );
            //获取JSON数据
            Map<String,Object> userInfo=JSON.parseObject(userInfoJson, Map.class);
            return DtoUtils.returnDataSuccess(userInfo);
        } catch (Exception e) {
            e.printStackTrace();
            return DtoUtils.returnFail(e.getMessage(), "488");
        }
    }

    /**
     * 会话保持
     * 1、保持和itrip的会话
     * 2、保持和wechat的会话
     * @return
     */

    @ApiOperation(value = "微信登录时客户端置换token", httpMethod = "POST",
            protocols = "HTTP", produces = "application/json",
            response = Dto.class,
            notes = "提供客户端置换token操作，服务器需要获取客户端header中的token串、refresh_token")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(paramType="header",required=true,name="token",value="用户认证凭据",defaultValue="token:PC-65e59e2bc836a297575c2e0cc191304f-38-20170725085123-ba081c"),
            @ApiImplicitParam(paramType="header",required=true,name="refreshtoken",value="用户微信刷新会话的凭据",defaultValue="809r0G5dkJLqnmFfopnf3ZIgFAN3qv30NVN4jHsnI6Bz6XQ3p6rllVl81_-GrJDsVhMOa69Fic4DWbVByq-8ix0olO_BFPGDuFuJdB8l0kU")
    })
    @RequestMapping(value = "/wechat/token/refresh", method = RequestMethod.POST,produces= "application/json")
    public @ResponseBody
    Dto wechatRefreshToken(HttpServletRequest request, HttpServletResponse response){

        String agent=request.getHeader("user-agent");
        String token=request.getHeader("token");
        String refreshToken=request.getHeader("refreshtoken");//此处header中的名称使用“_”不能获取

        try {
            //1、保持和itrip的会话
            ItripTokenVO itripTokenVO=tokenService.verifyToken(agent, token);
            String newToken = itripTokenVO.getToken();
            //2、保持和wechat的会话
            String refreshTokenUrl="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid="+WXLongConfig.APPID+"&grant_type=refresh_token&refresh_token="+refreshToken.trim();

            String json=UrlUtils.loadURL(refreshTokenUrl);
            Map<String,Object> wechatToken=JSON.parseObject(json, Map.class);
            if(null!=wechatToken.get("errcode")){
                return DtoUtils.returnFail(wechatToken.get("errmsg").toString(), "489");
            }

            //返回ItripWechatTokenVO (整合了本地会话与微信会话)
            ItripWechatTokenVO wechatTokenVO=new ItripWechatTokenVO(newToken,
                    Calendar.getInstance().getTimeInMillis()+ TokenService.SESSION_TIMEOUT*1000,//2h有效期
                    Calendar.getInstance().getTimeInMillis());
            wechatTokenVO.setAccessToken(wechatToken.get("access_token").toString());
            wechatTokenVO.setExpiresIn(wechatToken.get("expires_in").toString());
            wechatTokenVO.setRefreshToken(wechatToken.get("refresh_token").toString());
            wechatTokenVO.setOpenid(wechatToken.get("openid").toString());
            return DtoUtils.returnDataSuccess(wechatTokenVO);

        } catch (Exception e) {
            e.printStackTrace();
            return DtoUtils.returnFail(e.getMessage(), "487");
        }
    }
}
